//--------------------------------------------------------------------------------
// This file is part of the Windows Workflow Foundation Sample Code
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is intended only as a supplement to Microsoft
// Development Tools and/or on-line documentation.  See these other
// materials for detailed information regarding Microsoft code samples.
// 
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//--------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Globalization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;

namespace Microsoft.Samples.Workflow.UI.Design
{
    class ActivityOutputValueTypeConverter : TypeConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            TypeConverter realConverter = GetRealConverter(context);
            if (realConverter != null)
            {
                return realConverter.CanConvertTo(context, destinationType);
            }

            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            TypeConverter realConverter = GetRealConverter(context);
            if (realConverter != null)
            {
                return realConverter.ConvertTo(context, culture, value, destinationType);
            }
            else if (destinationType == typeof(string))
            {
                return System.Convert.ToString(value);
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            TypeConverter realConverter = GetRealConverter(context);
            if (realConverter != null)
            {
                return realConverter.CanConvertFrom(context, sourceType);
            }
            else if (context != null)
            {
                IDynamicPropertyTypeProvider dynamicTypeProvider = context.Instance as IDynamicPropertyTypeProvider;
                if (dynamicTypeProvider != null)
                {
                    Type propType = dynamicTypeProvider.GetPropertyType(context, context.PropertyDescriptor.Name);
                    if (propType != null && propType == sourceType)
                    {
                        return true;
                    }
                }
            }

            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object valueToConvert)
        {
            TypeConverter realConverter = GetRealConverter(context);
            if (realConverter != null)
            {
                return realConverter.ConvertFrom(context, culture, valueToConvert);
            }
            else if (context != null)
            {
                IDynamicPropertyTypeProvider dynamicTypeProvider = context.Instance as IDynamicPropertyTypeProvider;
                if (dynamicTypeProvider != null)
                {
                    Type propType = dynamicTypeProvider.GetPropertyType(context, context.PropertyDescriptor.Name);
                    if (propType != null && propType == valueToConvert.GetType())
                    {
                        return valueToConvert;
                    }
                }
            }

            return base.ConvertFrom(context, culture, valueToConvert);
        }

        private TypeConverter GetRealConverter(ITypeDescriptorContext context)
        {
            TypeConverter realConverter = null;

            if (context != null)
            {
                IDynamicPropertyTypeProvider dynamicTypeProvider = context.Instance as IDynamicPropertyTypeProvider;
                if (dynamicTypeProvider != null)
                {
                    Type propType = dynamicTypeProvider.GetPropertyType(context, context.PropertyDescriptor.Name);
                    if (propType != null)
                    {
                        TypeConverterAttribute[] convertAttribute = (TypeConverterAttribute[])propType.GetCustomAttributes(typeof(TypeConverterAttribute), true);
                        if (convertAttribute != null && convertAttribute.Length > 0)
                        {
                            try
                            {
                                Type converterType = null;
                                ITypeProvider typeProvider = context.GetService(typeof(ITypeProvider)) as ITypeProvider;
                                if (typeProvider != null)
                                {
                                    converterType = typeProvider.GetType(convertAttribute[0].ConverterTypeName);
                                }
                                else
                                {
                                    converterType = Type.GetType(convertAttribute[0].ConverterTypeName);
                                }

                                if (converterType != null)
                                {
                                    realConverter = Activator.CreateInstance(converterType) as TypeConverter;
                                }
                            }
                            catch
                            {
                                // Ignore exception.
                            }
                        }
                    }
                }
            }
            return realConverter;
        }
    }
}
